package Leo.social.QQ.Api;

import org.apache.cxf.common.util.StringUtils;
import org.springframework.http.converter.FormHttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.social.oauth2.AccessGrant;
import org.springframework.social.oauth2.OAuth2Template;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import java.nio.charset.Charset;

public class OAuth2TemplateForQQImpl extends OAuth2Template {
    /**
     * Constructs an OAuth2Template for a given set of client credentials.
     * Assumes that the authorization URL is the same as the authentication URL.
     *
     * @param clientId       the client ID
     * @param clientSecret   the client secret
     * @param authorizeUrl   the base URL to redirect to when doing authorization code or implicit grant authorization
     * @param accessTokenUrl the URL at which an authorization code, refresh token, or user credentials may be exchanged for an access token.
     */
    public OAuth2TemplateForQQImpl(String clientId, String clientSecret, String authorizeUrl, String accessTokenUrl) {
        super(clientId, clientSecret, authorizeUrl, accessTokenUrl);
        setUseParametersForClientAuthentication(true); // true时，才会在请求token时把client id和client secret发过去给服务提供商
    }

    /**
     * Creates the {@link RestTemplate} used to communicate with the provider's OAuth 2 API.
     * This implementation creates a RestTemplate with a minimal set of HTTP message converters ({@link FormHttpMessageConverter} and {@link MappingJackson2HttpMessageConverter}).
     * May be overridden to customize how the RestTemplate is created.
     * For example, if the provider returns data in some format other than JSON for form-encoded, you might override to register an appropriate message converter.
     *
     * @return a {@link RestTemplate} used to communicate with the provider's OAuth 2 API
     * QQ的token返回值不是json，而是一段文字，因此这里要添加文字转换器
     */
    @Override
    protected RestTemplate createRestTemplate() {
        RestTemplate restTemplate = super.createRestTemplate();
        restTemplate.getMessageConverters().add(new StringHttpMessageConverter(Charset.forName("UTF-8")));
        return restTemplate;
    }

    /**
     * Posts the request for an access grant to the provider.
     * The default implementation uses RestTemplate to request the access token and expects a JSON response to be bound to a Map. The information in the Map will be used to create an {@link AccessGrant}.
     * Since the OAuth 2 specification indicates that an access token response should be in JSON format, there's often no need to override this method.
     * If all you need to do is capture provider-specific data in the response, you should override createAccessGrant() instead.
     * However, in the event of a provider whose access token response is non-JSON, you may need to override this method to request that the response be bound to something other than a Map.
     * For example, if the access token response is given as form-encoded, this method should be overridden to call RestTemplate.postForObject() asking for the response to be bound to a MultiValueMap (whose contents can then be used to create an AccessGrant).
     *
     * @param accessTokenUrl the URL of the provider's access token endpoint.
     * @param parameters     the parameters to post to the access token endpoint.
     * @return the access grant.
     * QQ的token返回值不是json，而是一段文字。因此这里写如何解析这段文字
     */
    @Override
    protected AccessGrant postForAccessGrant(String accessTokenUrl, MultiValueMap<String, String> parameters) {
//        return super.postForAccessGrant(accessTokenUrl, parameters);
        String result = this.getRestTemplate().postForObject(accessTokenUrl, parameters, String.class);
        String[] split = StringUtils.split(result, "&");
        String token = split[0].substring(split[0].indexOf("=") + 1);
        Long expiresIn = new Long(split[1].substring(split[1].indexOf("=") + 1));
        String reflashToken = split[2].substring(split[2].indexOf("=") + 1);
        return new AccessGrant(token,null,reflashToken,expiresIn);
    }
}
